#pragma once
#include <jsoncpp/json/json.h>
#include <cstring>
#include <signal.h>
#include "./Compiler.hpp"
#include "./Runner.hpp"
#include "../comm/Request.hpp"
#include "../comm/Response.hpp"
namespace ns_compileandrun
{
    using namespace ns_compile;
    using namespace ns_runner;

    class CompileAndRun
    {
        // code > 0 收到信号
        // code < 0 非编译运行错误
        // code  == 0 整个过程成功
        static std::string Code2String(int code, const std::string &filename)
        {
            std::string content;
            switch (code)
            {
            case 0:
                return "compile and run success";
            case -1:
                return "The code passed in by the user is empty";
            case -2:
                return "unknow";
            case -3:
                FileUtil::ReadFile(filename, &content, true);
                return content;
            case -4:
                return "get filename error";
            case SIGSEGV:
                return strsignal(SIGSEGV);
            case SIGXCPU:
                return strsignal(SIGXCPU);
            case SIGABRT:
                return "内存超过限制";
            case SIGFPE:
                return strsignal(SIGFPE);
            default:
                return "unknow: " + std::to_string(code);
            }
        }
        /***************************************
         * 输入:
         * code： 用户提交的代码
         * input: 用户给自己提交的代码对应的输入，不做处理
         * cpu_limit: 时间要求
         * mem_limit: 空间要求
         *
         * 输出:
         * 必填
         * status: 状态码
         * reason: 请求结果原因
         * 选填：
         * stdout: 我的程序运行完的结果
         * stderr: 我的程序运行完的错误结果
         *
         * 参数：
         * in_json: {"code": "#include...", "input": "","cpu_limit":1, "mem_limit":10240}
         * out_json: {"status":"0", "reason":"","stdout":"","stderr":"",}
         * ************************************/
    public:
        static void Start(const std::string &injson, std::string *outjson)
        {
            
            // LOG(LogLevel::DEBUG) << injson;
            int status = 0;       // respond: status
            std::string reason;   // respond: reason
            std::string filename; // 编译并运行的src
            int run_signo;

            // 1. 将收到的请求反序列化
            ns_request::Request request;
            request.DeSerialize(injson);
// #define debug
#ifdef debug
LOG(LogLevel::DEBUG) << code;
// LOG(LogLevel::DEBUG) << input;
LOG(LogLevel::DEBUG) << cpu_limit;
LOG(LogLevel::DEBUG) << mem_limit;
#endif
            // 2.请求编译和运行服务，不同的结果对status进行赋值
            if (request.code.empty())
            {
                status = -1;
                goto END;
            }
            // 1.获取唯一文件名
            filename = FileUtil::GetUniqueFileName();
            if (filename.empty())
            {
                status = -4;
                goto END;
            }
            // 向src中写入源代码和测试用例
            if (!FileUtil::Write2File(PathUtil::Src(filename), request.code, request.input))
            {
                status = -2;
                goto END;
            }

            if (!Compiler::Compile(filename))
            {
                status = -3;
                goto END;
            }
            // 差错处理
            // >0说明收到信号
            run_signo = Runner::Run(filename, request.cpu_limit, request.mem_limit); // 差错处理
            if (run_signo < 0)
            {
                status = -2;
            }
            else if (run_signo > 0)
            {
                status = run_signo;
            }
            else
            {
                status = 0;
            }

        // 序列化
        END:
        {
            // 3.构建应答！
            ns_response::Response response; 
            response.status = status;
            response.reason = Code2String(status, PathUtil::compile_error(filename));
            if (status == 0)
            {
                std::string strstdout, strstderr;
                FileUtil::ReadFile(PathUtil::Stdout(filename), &strstdout, true);
                FileUtil::ReadFile(PathUtil::Stderr(filename), &strstderr, true);
                response.stdout = strstdout;
                response.stderr = strstderr;
            }
            *outjson = response.Serialize();
        }

            // sleep(5); // ForDebug
            // FileUtil::ResourceClean(filename);  // 清理不必要的垃圾文件，生成的临时文件
        }
    };
}
